﻿using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using WxLib.Common;
using WxLib.Core.RequestHandlers;

namespace WxLib.CustomerService
{
    public class WxCustomerMessageService
    {
        private readonly WxApiOptions options;

        /// <summary>
        /// 获取或设置用于执行请求的RequestHandler
        /// </summary>
        public IPostRequestHandler RequestHandler;

        /// <summary>
        /// 获取或设置HTTP请求协议
        /// </summary>
        public HttpMethod Method { get; set; }

        public WxCustomerMessageService(IOptions<WxApiOptions> optionsAccessor)
        {
            this.options = optionsAccessor.Value;
            Method = HttpMethod.Post;
            RequestHandler = new RequestHandler(new WxLib.Core.Serializers.JsonSerializer());
        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="token"></param>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <returns></returns>
        public bool CheckSignature(string token, string signature, string timestamp, string nonce)
        {
            string[] ArrTmp = { token, timestamp, nonce };
            Array.Sort(ArrTmp);
            string tmpStr = string.Join(string.Empty, ArrTmp);
            tmpStr = WxUtil.SHA1Sign(tmpStr);
            tmpStr = tmpStr.ToLower();
            if (tmpStr == signature)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 上传临时图片
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="fileData"></param>
        /// <returns></returns>
        public async Task<UoloadMediaResult> UploadTempImageAsync(string fileName, byte[] fileData)
        {
            WxAccessTokenResponse response = await WxCommonApi.Instance().GetAccessTokenAsync(options.AppId, options.AppSecret);
            string access_token = response.access_token;

            string url = $"https://api.weixin.qq.com/cgi-bin/media/upload?access_token={access_token}&type=image";

            var boundary = "fbce142e-4e8e-4bf3-826d-cc3cf506cccc";
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("User-Agent", "KnowledgeCenter");
            client.DefaultRequestHeaders.Remove("Expect");
            client.DefaultRequestHeaders.Remove("Connection");
            client.DefaultRequestHeaders.ExpectContinue = false;
            client.DefaultRequestHeaders.ConnectionClose = true;
            var content = new MultipartFormDataContent(boundary);
            content.Headers.Remove("Content-Type");
            content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
            var contentByte = new ByteArrayContent(fileData);
            content.Add(contentByte);
            contentByte.Headers.Remove("Content-Disposition");
            contentByte.Headers.TryAddWithoutValidation("Content-Disposition", $"form-data; name=\"media\";filename=\"{fileName}\"" + "");
            contentByte.Headers.Remove("Content-Type");
            contentByte.Headers.TryAddWithoutValidation("Content-Type", "image/png");
            try
            {
                var result2 = await client.PostAsync(url, content);
                if (result2.StatusCode != HttpStatusCode.OK)
                    throw new Exception(await result2.Content.ReadAsStringAsync());
                string jsonstr = await result2.Content.ReadAsStringAsync();

                //LogFactory.GetLogger<ApiController>().LogInformation($"接收上传临时素材结果:{jsonstr}");
                var result = JsonConvert.DeserializeObject<UoloadMediaResult>(jsonstr);
                if (result.errcode == 42001 || result.errcode == 40001)
                {
                    WxCommonApi.Instance().Reload = true;
                }
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message + ex.InnerException.Message);
            }

        }

        /// <summary>
        /// 发送图片消息
        /// </summary>
        /// <param name="touser"></param>
        /// <param name="mediaId"></param>
        /// <returns></returns>
        public async Task<SendMessageResult> SendImageMessageAsync(string touser, string mediaId)
        {
            WxAccessTokenResponse response = await WxCommonApi.Instance().GetAccessTokenAsync(options.AppId, options.AppSecret);
            string access_token = response.access_token;
            string relUri = $"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={access_token}";
            ImageMessageOptions msgOptions = ImageMessageOptions.New(touser, mediaId);
            var queryString = RequestHandler.Serializer.Serialize(msgOptions);
            var result = await requestAsync<SendMessageResult>(relUri, queryString, Method);
            if (result.errcode == 42001 || result.errcode == 40001)
            {
                WxCommonApi.Instance().Reload = true;
            }
            return result;
        }

        public ImageMessageOptions GetImageMessageOptions(string touser, string mediaId)
        {
            return ImageMessageOptions.New(touser, mediaId);
        }

        /// <summary>
        /// 发送文本消息
        /// </summary>
        /// <param name="touser"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task<SendMessageResult> SendTextMessageAsync(string touser, string message)
        {
            WxAccessTokenResponse response = await WxCommonApi.Instance().GetAccessTokenAsync(options.AppId, options.AppSecret);
            string access_token = response.access_token;
            string relUri = $"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={access_token}";
            TextMessageOptions msgOptions = TextMessageOptions.New(touser, message);
            var queryString = RequestHandler.Serializer.Serialize(msgOptions);
            var result = await requestAsync<SendMessageResult>(relUri, queryString, Method);
            if (result.errcode == 42001 || result.errcode == 40001)
            {
                WxCommonApi.Instance().Reload = true;
            }
            return result;
        }

        public TextMessageOptions GetTextMessageOptions(string touser, string message)
        {
            return TextMessageOptions.New(touser, message);
        }

        /// <summary>
        /// 异步请求 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="relUri"></param>
        /// <param name="queryString"></param>
        /// <param name="method"></param>
        /// <returns></returns>
        private async Task<T> requestAsync<T>(string relUri, string queryString, HttpMethod method)
        {
            if (method == HttpMethod.Post)
            {
                return await RequestHandler.PostRequestAsync<T>(new Uri(relUri), queryString).ConfigureAwait(false);
            }
            var uri = new Uri(relUri + "?" + queryString);
            return await RequestHandler.RequestAsync<T>(uri).ConfigureAwait(false);
        }
    }
}
